home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
a86v302b.arc
/
06INSTR.DOC
next >
Wrap
Text File
|
1987-04-08
|
42KB
|
715 lines
CHAPTER 6 THE 86 INSTRUCTION SET 6-1
Since this is the start of the A86VxxxB.ARC file, I'll repeat
here that the entire A86 package is Copyright (C)1986--1987 Eric
Isaacson. All rights reserved. If this is all you've got, you
need to get A86VxxxA.ARC, which contains the program and the
first half of the manual.
Effective Addresses
Most memory data accessing in the 86 family is accomplished via
the mechanism of the effective address. Wherever an effective
address specifier "eb", "ew" or "ed" appears in the list of 8086
instructions, you may use a wide variety of actual operands in
that instruction. These include general registers, memory
variables, and a variety of indexed memory quantities.
GENERAL REGISTERS: Wherever an "ew" appears, you can use any of
the 16-bit registers AX,BX,CX,DX,SI,DI,SP, or BP. Wherever an
"eb" appears, you can use any of the 8-bit registers
AL,BL,CL,DL,AH,BH,CH, or DH. For example, the "ADD ew,rw"
form subsumes the 16-bit register-to-register adds; for
example, ADD AX,BX; ADD SI,BP; ADD SP,AX.
MEMORY VARIABLES: Wherever an "ew" appears, you can use a word-
memory-variable. Wherever an "eb" appears, you can use a
byte-memory-variable. Variables are typically declared in the
DATA segment, using a DW declaration for a word-variable, or a
DB declaration for a byte-variable. For example, you can
declare variables:
DATA_PTR DW ?
ESC_CHAR DB ?
Later, you can load or store these variables:
MOV SI,DATA_PTR ; load DATA_PTR into SI for use
LODSW ; fetch the word pointed to by DATA_PTR
MOV DATA_PTR,SI ; store the value incremented by the LODSW
MOV BL,ESC_CHAR ; load the byte-variable ESC_CHAR
Alternatively, you can address specific unnamed memory
locations by enclosing the location value in square brackets;
for example,
MOV AL,[02000] ; load contents of location 02000 into AL
Note that A86 discerned from context (loading into AL) that a
BYTE at 02000 was intended. Sometimes this is impossible, and
you must specify byte or word:
INC B[02000] ; increment the byte at location 02000
MOV W[02000],0 ; set the WORD at location 02000 to zero
6-2
INDEXED MEMORY: The 86 supports the use of certain registers as
base pointers and index registers into memory. BX and BP are
the base registers; SI and DI are the index registers. You
may combine at most one base register, at most one index
register, and a constant number into a run-time pointer that
determines the location of the effective address memory to be
used in the instruction. These can be given explicitly, by
enclosing the index registers in brackets:
MOV AX,[BX]
MOV CX,W[SI+17]
MOV AX,[BX+BP+5]
MOV AX,[BX][BP]5 ; another way to write the same instr.
Or, indexing can be accomplished by declaring variables in a
based structure:
STRUC [BP] ; NOTE based structures are unique to A86!
BP_SAVE DW ?
RET_ADDR DW ?
PARM1 DW ?
PARM2 DW ?
ENDS
INC PARM1 ; equivalent to INC W[BP+4]
Finally, indexing can be done by mixing explicit components
with declared ones:
TABLE DB 4,2,1,3,5
MOV AL,TABLE[BX]
Segmentation and Effective Addresses
The 86 family has four segment registers, CS, DS, ES, and SS,
used to address memory. Each segment register points to 64K
bytes of memory within the 1-megabyte memory space of the 86.
(The start of the 64K is calculated by multiplying the segment
register value by 16; i.e., by shifting the value left by one hex
digit.) If your program's code, data and stack areas can all fit
in the same 64K bytes, you can leave all the segment registers
set to the same value. In that case, you won't have to think
about segment registers--no matter which one is used to address
memory, you'll still get the same 64K. If your program needs
more than 64K, you must point one or more segment registers to
other parts of the memory space. In this case, you must take
care that your memory references use the segment registers you
intended.
Each effective address memory access has a default segment
register, to be used if you do not explicitly specify which
segment register you wish. For most effective addresses, the
default segment register is DS. The exceptions are those
effective addresses that use the BP register for indexing. All
BP-indexed memory references have a default of SS. (This is
because BP is intended to be used for addressing local variables,
stored on the stack.)
6-3
If you wish your memory access to use a different segment
register, you provide a segment-override byte before the
instruction containing the effective address operand. In the A86
language, you code the override by giving the name of the segment
register you wish before the instruction mnemonic. For example,
suppose you want to load the AL register with the memory byte
pointed to by BX. If you code MOV AL,[BX], the DS register will
be used to determine which 64K segment BX is pointing to. If you
want the byte to come from the CS-segment instead, you code CS
MOV AL,[BX]. Be aware that the segment-override byte has effect
only upon the single instruction that follows it. If you have a
sequence of instructions requiring overrides, you must give an
override byte before every instruction in the sequence. (In that
case, you may wish to consider changing the value of the default
segment register for the duration of the sequence.)
NOTE: This method for providing segment-overrides is unique to
the A86 assembler! The assemblers provided by Intel and IBM (MS-
DOS) attempt to figure out segment allocation for you, and plug
in segment-override bytes "behind your back". In order to do
this, those assemblers require you to inform them which variables
and structures are pointed to by which segment registers. That
is what the ASSUME directive in those assemblers is all about. I
wrote Intel's first 86 assembler, ASM86, so I have been watching
the situation since day one. Over the years, I have concluded
that the ASSUME-mechanism creates far, far more confusion that it
solves. So I scrapped it; and the result is an assembler with
far less red tape. But if your program needs more than 64K, you
do have to manage those segment registers yourself; so take care!
Effective Use of Effective Addresses
Remember that all of the common instructions of the 86 family
allow effective addresses as operands. (The only major functions
that don't are the AL/AX specific ones: multiply, divide, and
input/output). This means that you don't have to funnel many
through AL or AX just to do something with them. You can perform
all the common arithmetic, PUSH/POP, and MOVes from any general
register to any general register; from any memory location
(indexed if you like) to any register; and (this is most often
overlooked) from any register TO memory. The only thing you
can't do in general is memory-to-memory. Among the more common
operations that inexperienced 86 programmers overlook are:
* setting memory variables to immediate values
* testing memory variables, and comparing them to constants
* preserving memory variables by PUSHing and POPping them
* incrementing and decrementing memory variables
* adding into memory variables
6-4
Encoding of Effective Addresses
Unless you are concerned with the nitty-gritty details of 86
instruction encoding, you don't need to read this section.
Every instruction with an effective address has an encoded byte,
known as the effective address byte, following the 1-byte opcode
for the instruction. (For obscure reasons, Intel calls this byte
the ModRM byte.) If the effective address is a memory variable,
or an indexed memory location with a non-zero constant offset,
then the effective address byte will be immediately followed by
the offset amount. Amounts in the range -128 to +127 are given
by a single signed byte, denoted by "d8" in the table below.
Amounts requiring a 2-byte representation are denoted by "d16" in
the table below. As with all 16-bit memory quantities in the 86
family, the word is stored with the least significant byte FIRST.
The following table of effective address byte values is organized
into 32 rows and 8 columns. The 32 rows give the possible values
for the effective address operand: 8 registers and 24 memory
indexing modes. A 25th indexing mode, [BP] with zero
displacement, has been pre-empted by the simple-memory-variable
case. If you code [BP] with no displacement, you will get
[BP]+d8, with a d8-value of zero.
The 8 columns of the table reflect further information given by
the effective address byte. Usually, this is the identity of the
other (always a register) operand of a 2-operand instruction.
Those instructions are identified by a "/r" following the opcode
byte in the instruction list. Sometimes, the information given
supplements the opcode byte in identifying the instruction
itself. Those instructions are identified by a "/" followed by a
digit from 0 through 7. The digit tells which of the 8 columns
you should use to find the effective address byte.
For example, suppose you have a perverse wish to know the precise
bytes encoded by the instruction SUB B[BX+17],100. This
instruction subtracts an immediate quantity, 100, from an
effective address quantity, B[BX+17]. By consulting the
instruction list, you find the general form SUB eb,ib. The
opcode bytes given there are 80 /5 ib. The "/5" denotes an
effective-address byte, whose value will be taken from column 5
of the table below. The offset 17 decimal, which is 11 hex, will
fit in a single "d8" byte, so we take our value from the "[BX] +
d8" row. The table tells us that the effective address byte is
6F. Immediately following the 6F is the offset, 11 hex.
Following that is the ib-value of 100 decimal, which is 64 hex.
So the bytes generated by SUB B[BX+17],100 are 80 6F 11 64.
6-5
Table of Effective Address byte values
s = ES CS SS DS
rb = AL CL DL BL AH CH DH BH
rw = AX CX DX BX SP BP SI DI
digit= 0 1 2 3 4 5 6 7
Effective
EA byte address:
values: 00 08 10 18 20 28 30 38 [BX + SI]
01 09 11 19 21 29 31 39 [BX + DI]
02 0A 12 1A 22 2A 32 3A [BP + SI]
03 0B 13 1B 23 2B 33 3B [BP + DI]
04 0C 14 1C 24 2C 34 3C [SI]
05 0D 15 1D 25 2D 35 3D [DI]
06 0E 16 1E 26 2E 36 3E d16 (simple var)
07 0F 17 1F 27 2F 37 3F [BX]
40 48 50 58 60 68 70 78 [BX + SI] + d8
41 49 51 59 61 69 71 79 [BX + DI] + d8
42 4A 52 5A 62 6A 72 7A [BP + SI] + d8
43 4B 53 5B 63 6B 73 7B [BP + DI] + d8
44 4C 54 5C 64 6C 74 7C [SI] + d8
45 4D 55 5D 65 6D 75 7D [DI] + d8
46 4E 56 5E 66 6E 76 7E [BP] + d8
47 4F 57 5F 67 6F 77 7F [BX] + d8
80 88 90 98 A0 A8 B0 B8 [BX + SI] + d16
81 89 91 99 A1 A9 B1 B9 [BX + DI] + d16
82 8A 92 9A A2 AA B2 BA [BP + SI] + d16
83 8B 93 9B A3 AB B3 BB [BP + DI] + d16
84 8C 94 9C A4 AC B4 BC [SI] + d16
85 8D 95 9D A5 AD B5 BD [DI] + d16
86 8E 96 9E A6 AE B6 BE [BP] + d16
87 8F 97 9F A7 AF B7 BF [BX] + d16
C0 C8 D0 D8 E0 E8 F0 F8 ew=AX eb=AL
C1 C9 D1 D9 E1 E9 F1 F9 ew=CX eb=CL
C2 CA D2 DA E2 EA F2 FA ew=DX eb=DL
C3 CB D3 DB E3 EB F3 FB ew=BX eb=BL
C4 CC D4 DC E4 EC F4 FC ew=SP eb=AH
C5 CD D5 DD E5 ED F5 FD ew=BP eb=CH
C6 CE D6 DE E6 EE F6 FE ew=SI eb=DH
C7 CF D7 DF E7 EF F7 FF ew=DI eb=BH
d8 denotes an 8-bit displacement following the EA byte,
to be sign-extended and added to the index.
d16 denotes a 16-bit displacement following the EA byte,
to be added to the index.
Default segment register is SS for effective addresses containing
a BP index; DS for other memory effective addresses.
6-6
How to Read the Instruction Set Chart
The chart below summarizes the machine instructions you can
program with A86. In order to use the chart, you need to learn
the meanings of the specifiers (each given by 2 lower-case
letters), that follow most of the instruction mnemonics. Each
specifier indicates the type of operand (register byte, immediate
word, etc.) that follows the mnemonic to produce the given
opcodes.
"c" means the operand is a code label, pointing to a part of the
program to be jumped to or called. A86 will also accept a
constant offset in this place (or a constant segment-offset
pair in the case of "cd"). "cb" is a label within about 128
bytes (in either direction) of the current location. "cw" is
a label within the same code segment as this program; "cd" is
a pair of constants separated by a colon-- the segment value
to the left of the colon, and the offset to the right. Note
that in both the cb and cw cases, the object code generated
is the offset from the location following the current
instruction, not the absolute location of the label operand.
In some assemblers (most notably for the Z-80 processor) you
have to code this offset explicitly by putting "$-" before
every relative jump operand in your source code. You do NOT
need to, and should not do so with A86.
"e" means the operand is an Effective Address. The concept of an
Effective Address is central to the 86 machine architecture,
and thus to 86 assembly language programming. It is
described in detail at the start of Chapter 8. We summarize
here by saying that an Effective Address is either a general-
purpose register, a memory variable, or an indexed memory
quantity. For example, the instruction "ADD rb,eb" includes
the instructions: ADD AL,BL, or ADD CH,BYTEVAR, or ADD
DL,B[BX+17].
"i" means the operand is an immediate constant, provided as part
of the instruction itself. "ib" is a byte-sized constant;
"iw" is a constant occupying a full 16-bit word. The operand
can also be a label, defined with a colon. In that case, the
immediate constant which is the location of the label is
used. Examples: "MOV rw,iw" includes the instructions: MOV
AX,17, or MOV SI,VAR_ARRAY, where "VAR_ARRAY:" appears
somewhere in the program, defined with a colon. NOTE that if
VAR_ARRAY were defined without a colon, e.g., "VAR_ARRAY DW
1,2,3", then "MOV SI,VAR_ARRAY" would be a "MOV rw,ew" NOT a
"MOV rw,iw". The MOV would move the contents of memory at
VAR_ARRAY (in this case 1) into SI, instead of the location
of the memory. To load the location, you can code "MOV
SI,OFFSET VAR_ARRAY".
"m" means a memory variable or an indexed memory quantity; i.e.,
any Effective Address EXCEPT a register.
"r" means the operand is a general-purpose register. The 8 "rb"
registers are AL,BL,CL,DL,AH,BH,CH,DH; the 8 "rw" registers
are AX,BX,CX,DX,SI, DI,BP,SP.
6-7
WARNING: Instruction forms marked with "*" by the mnemonic are
part of the extended 186/286/NEC instruction set.
Instructions marked with "#" are unique to the NEC
processors. These instructions will NOT work on the 8088 of
the IBM-PC; nor will they work on the 8086; nor will the NEC
instructions work on the 186 or 286. If you wish your
programs to run on all PC's, do not use these instructions!
Opcodes Instruction Description
------- ----------- -----------
37 AAA ASCII adjust AL (carry into AH) after addition
D5 0A AAD ASCII adjust before division (AX = 10*AH + AL)
D4 0A AAM ASCII adjust after multiply (AL/10: AH=Quo AL=Rem)
3F AAS ASCII adjust AL (borrow from AH) after subtraction
14 ib ADC AL,ib Add with carry immediate byte into AL
15 iw ADC AX,iw Add with carry immediate word into AX
80 /2 ib ADC eb,ib Add with carry immediate byte into EA byte
10 /r ADC eb,rb Add with carry byte register into EA byte
83 /2 ib ADC ew,ib Add with carry immediate byte into EA word
81 /2 iw ADC ew,iw Add with carry immediate word into EA word
11 /r ADC ew,rw Add with carry word register into EA word
12 /r ADC rb,eb Add with carry EA byte into byte register
13 /r ADC rw,ew Add with carry EA word into word register
04 ib ADD AL,ib Add immediate byte into AL
05 iw ADD AX,iw Add immediate word into AX
80 /0 ib ADD eb,ib Add immediate byte into EA byte
00 /r ADD eb,rb Add byte register into EA byte
83 /0 ib ADD ew,ib Add immediate byte into EA word
81 /0 iw ADD ew,iw Add immediate word into EA word
01 /r ADD ew,rw Add word register into EA word
02 /r ADD rb,eb Add EA byte into byte register
03 /r ADD rw,ew Add EA word into word register
0F 20 #ADD4S Add CL nibbles BCD from DS:SI into ES:DI (CL even,NZ)
24 ib AND AL,ib Logical-AND immediate byte into AL
25 iw AND AX,iw Logical-AND immediate word into AX
80 /4 ib AND eb,ib Logical-AND immediate byte into EA byte
20 /r AND eb,rb Logical-AND byte register into EA byte
81 /4 iw AND ew,iw Logical-AND immediate word into EA word
21 /r AND ew,rw Logical-AND word register into EA word
22 /r AND rb,eb Logical-AND EA byte into byte register
23 /r AND rw,ew Logical-AND EA word into word register
63 /r *ARPL ew,rw Adjust RPL of EA word not smaller than RPL of rw
62 /r *BOUND rw,md INT 5 if rw not between [md] and [md+2] inclusive
9A cd CALL cd Call far segment, immediate 4-byte address
E8 cw CALL cw Call near, offset relative to next instruction
FF /3 CALL ed Call far segment, address at EA doubleword
FF /2 CALL ew Call near, offset absolute at EA word
0F FF ib #CALL80 ib Call 8080-emulation code at INT number ib
98 CBW Convert byte into word (AH = top bit of AL)
F8 CLC Clear carry flag
FC CLD Clear direction flag so SI and DI will increment
FA CLI Clear interrupt enable flag; interrupts disabled
0F 12/0 #CLRBIT eb,CL Clear bit CL of eb
0F 13/0 #CLRBIT ew,CL Clear bit CL of ew
0F 1A/0 ib #CLRBIT eb,ib Clear bit ib of eb
0F 1B/0 ib #CLRBIT ew,ib Clear bit ib of ew
6-8
0F 06 *CLTS Clear task switched flag
F5 CMC Complement carry flag
3C ib CMP AL,ib Subtract immediate byte from AL for flags only
3D iw CMP AX,iw Subtract immediate word from AX for flags only
80 /7 ib CMP eb,ib Subtract immediate byte from EA byte for flags only
38 /r CMP eb,rb Subtract byte register from EA byte for flags only
83 /7 ib CMP ew,ib Subtract immediate byte from EA word for flags only
81 /7 iw CMP ew,iw Subtract immediate word from EA word for flags only
39 /r CMP ew,rw Subtract word register from EA word for flags only
3A /r CMP rb,eb Subtract EA byte from byte register for flags only
3B /r CMP rw,ew Subtract EA word from word register for flags only
0F 26 #CMP4S Compare CL nibbles CD at DS:SI from ES:DI (CL even,NZ)
A6 CMPS mb,mb Compare bytes ES:[DI] from [SI], advance SI and DI
A7 CMPS mw,mw Compare words ES:[DI] from [SI], advance SI and DI
A6 CMPSB Compare bytes ES:[DI] from DS:[SI], advance SI and DI
A7 CMPSW Compare words ES:[DI] from DS:[SI], advance SI and DI
99 CWD Convert word to doubleword (DX = top bit of AX)
27 DAA Decimal adjust AL after addition
2F DAS Decimal adjust AL after subtraction
FE /1 DEC eb Decrement EA byte by 1
FF /1 DEC ew Decrement EA word by 1
48+rw DEC rw Decrement word register by 1
F6 /6 DIV eb Unsigned divide AX by EA byte (AL=Quo AH=Rem)
F7 /6 DIV ew Unsigned divide DXAX by EA word (AX=Quo DX=Rem)
C8 iw 00 *ENTER iw,0 Make stack frame, iw bytes local storage, 0 levels
C8 iw 01 *ENTER iw,1 Make stack frame, iw bytes local storage, 1 level
C8 iw ib *ENTER iw,ib Make stack frame, iw bytes local storage, ib levels
Fany Floating point set is in Chapter 7
F4 HLT Halt
F6 /7 IDIV eb Signed divide AX by EA byte (AL=Quo AH=Rem)
F7 /7 IDIV ew Signed divide DXAX by EA word (AX=Quo DX=Rem)
F6 /5 IMUL eb Signed multiply (AX = AL * EA byte)
F7 /5 IMUL ew Signed multiply (DXAX = AX * EA word)
6B /r ib *IMUL rw,ib Signed multiply immediate byte into word register
69 /r iw *IMUL rw,iw Signed multiply immediate word into word register
69 /r iw *IMUL rw,ew,iw Signed multiply (rw = EA word * immediate word)
6B /r ib *IMUL rw,ew,ib Signed multiply (rw = EA word * immediate byte)
E4 ib IN AL,ib Input byte from immediate port into AL
EC IN AL,DX Input byte from port DX into AL
E5 ib IN AX,ib Input word from immediate port into AX
ED IN AX,DX Input word from port DX into AX
FE /0 INC eb Increment EA byte by 1
FF /0 INC ew Increment EA word by 1
40+rw INC rw Increment word register by 1
6C *INS eb,DX Input byte from port DX into [DI]
6D *INS ew,DX Input word from port DX into [DI]
6C *INSB Input byte from port DX into ES:[DI]
6D *INSW Input word from port DX into ES:[DI]
CC INT 3 Interrupt 3 (trap to debugger) (far call, with flags
CD ib INT ib Interrupt numbered by immediate byte pushed first)
CE INTO Interrupt 4 if overflow flag is 1
CF IRET Interrupt return (far return and pop flags)
6-9
77 cb JA cb Jump short if above (CF=0 and ZF=0) above=UNSIGNED
73 cb JAE cb Jump short if above or equal (CF=0)
72 cb JB cb Jump short if below (CF=1) below=UNSIGNED
76 cb JBE cb Jump short if below or equal (CF=1 or ZF=1)
72 cb JC cb Jump short if carry (CF=1)
E3 cb JCXZ cb Jump short if CX register is zero
74 cb JE cb Jump short if equal (ZF=1)
7F cb JG cb Jump short if greater (ZF=0 and SF=OF) greater=SIGNED
7D cb JGE cb Jump short if greater or equal (SF=OF)
7C cb JL cb Jump short if less (SF/=OF) less=SIGNED
7E cb JLE cb Jump short if less or equal (ZF=1 or SF/=OF)
EB cb JMP cb Jump short (signed byte relative to next instruction)
EA cd JMP cd Jump far (4-byte immediate address)
E9 cw JMP cw Jump near (word offset relative to next instruction)
FF /4 JMP ew Jump near to EA word (absolute offset)
FF /5 JMP md Jump far (4-byte address in memory doubleword)
76 cb JNA cb Jump short if not above (CF=1 or ZF=1)
72 cb JNAE cb Jump short if not above or equal (CF=1)
73 cb JNB cb Jump short if not below (CF=0)
77 cb JNBE cb Jump short if not below or equal (CF=0 and ZF=0)
73 cb JNC cb Jump short if not carry (CF=0)
75 cb JNE cb Jump short if not equal (ZF=0)
7E cb JNG cb Jump short if not greater (ZF=1 or SF/=OF)
7C cb JNGE cb Jump short if not greater or equal (SF/=OF)
7D cb JNL cb Jump short if not less (SF=OF)
7F cb JNLE cb Jump short if not less or equal (ZF=0 and SF=OF)
71 cb JNO cb Jump short if not overflow (OF=0)
7B cb JNP cb Jump short if not parity (PF=0)
79 cb JNS cb Jump short if not sign (SF=0)
75 cb JNZ cb Jump short if not zero (ZF=0)
70 cb JO cb Jump short if overflow (OF=1)
7A cb JP cb Jump short if parity (PF=1)
7A cb JPE cb Jump short if parity even (PF=1)
7B cb JPO cb Jump short if parity odd (PF=0)
78 cb JS cb Jump short if sign (SF=1)
74 cb JZ cb Jump short if zero (ZF=1)
9F LAHF Load: AH = flags SF ZF xx AF xx PF xx CF
0F 02 /r *LAR rw,ew Load: high(rw) = Access Rights byte, selector ew
C5 /r LDS rw,ed Load EA doubleword into DS and word register
8D /r LEA rw,m Calculate EA offset given by M, place in rw
C9 *LEAVE Set SP to BP, then POP BP (reverses previous ENTER)
C4 /r LES rw,ed Load EA doubleword into ES and word register
0F 01 /2 *LGDT m Load 6 bytes at m into Global Descriptor Table reg
0F 01 /3 *LIDT m Load 6 bytes at m into Interrupt Descriptor Table reg
0F 00 /2 *LLDT ew Load selector ew into Local Descriptor Table reg
0F 01 /6 *LMSW ew Load EA word into Machine Status Word
F0 LOCK (prefix) Assert BUSLOCK signal for the next instruction
0F 33/r #LODBITS rb,rb Load AX with DS:SI,bit rb (incr. SI,rb), rb+1 bits
0F 3B/0 ib #LODBITS rb,ib Load AX with DS:SI,bit rb (incr. SI,rb), ib+1 bits
AC LODS mb Load byte [SI] into AL, advance SI
AD LODS mw Load byte [SI] into AL, advance SI
AC LODSB Load byte [SI] into AL, advance SI
AD LODSW Load byte [SI] into AL, advance SI
6-10
E2 cb LOOP cb noflags DEC CX; jump short if CX/=0
E1 cb LOOPE cb noflags DEC CX; jump short if CX/=0 and equal (ZF=1)
E0 cb LOOPNE cb noflags DEC CX; jump short if CX/=0 and not equal
E0 cb LOOPNZ cb noflags DEC CX; jump short if CX/=0 and ZF=0
E1 cb LOOPZ cb noflags DEC CX; jump short if CX/=0 and zero (ZF=1)
0F 03 /r *LSL rw,ew Load: rw = Segment Limit, selector ew
0F 00 /3 *LTR ew Load EA word into Task Register
A0 iw MOV AL,xb Move byte variable (offset iw) into AL
A1 iw MOV AX,xw Move word variable (offset iw) into AX
8E /3 MOV DS,mw Move memory word into DS
8E /3 MOV DS,rw Move word register into DS
C6 /0 ib MOV eb,ib Move immediate byte into EA byte
88 /r MOV eb,rb Move byte register into EA byte
8E /0 MOV ES,mw Move memory word into ES
8E /0 MOV ES,rw Move word register into ES
8C /1 MOV ew,CS Move CS into EA word
8C /3 MOV ew,DS Move DS into EA word
C7 /0 iw MOV ew,iw Move immediate word into EA word
8C /0 MOV ew,ES Move ES into EA word
89 /r MOV ew,rw Move word register into EA word
8C /2 MOV ew,SS Move SS into EA word
B0+rb ib MOV rb,ib Move immediate byte into byte register
8A /r MOV rb,eb Move EA byte into byte register
B8+rw iw MOV rw,iw Move immediate word into word register
8B /r MOV rw,ew Move EA word into word register
8E /2 MOV SS,mw Move memory word into SS
8E /2 MOV SS,rw Move word register into SS
A2 iw MOV xb,AL Move AL into byte variable (offset iw)
A3 iw MOV xw,AX Move AX into word register (offset iw)
A4 MOVS mb,mb Move byte [SI] to ES:[DI], advance SI and DI
A5 MOVS mw,mw Move word [SI] to ES:[DI], advance SI and DI
A4 MOVSB Move byte DS:[SI] to ES:[DI], advance SI and DI
A5 MOVSW Move word DS:[SI] to ES:[DI], advance SI and DI
F6 /4 MUL eb Unsigned multiply (AX = AL * EA byte)
F7 /4 MUL ew Unsigned multiply (DXAX = AX * EA word)
F6 /3 NEG eb Two's complement negate EA byte
F7 /3 NEG ew Two's complement negate EA word
NIL (prefix) Special "do-nothing" opcode assembles no code
90 NOP No Operation
F6 /2 NOT eb Reverse each bit of EA byte
F7 /2 NOT ew Reverse each bit of EA word
0F 16/0 #NOTBIT eb,CL Complement bit CL of eb
0F 17/0 #NOTBIT ew,CL Complement bit CL of ew
0F 1E/0 ib #NOTBIT eb,ib Complement bit ib of eb
0F 1F/0 ib #NOTBIT ew,ib Complement bit ib of ew
0C ib OR AL,ib Logical-OR immediate byte into AL
0D iw OR AX,iw Logical-OR immediate word into AX
80 /1 ib OR eb,ib Logical-OR immediate byte into EA byte
08 /r OR eb,rb Logical-OR byte register into EA byte
81 /1 iw OR ew,iw Logical-OR immediate word into EA word
09 /r OR ew,rw Logical-OR word register into EA word
0A /r OR rb,eb Logical-OR EA byte into byte register
0B /r OR rw,ew Logical-OR EA word into word register
6-11
E6 ib OUT ib,AL Output byte AL to immediate port number ib
E7 ib OUT ib,AX Output word AX to immediate port number ib
EE OUT DX,AL Output byte AL to port number DX
EF OUT DX,AX Output word AX to port number DX
6E *OUTS DX,eb Output byte [SI] to port number DX, advance SI
6F *OUTS DX,ew Output word [SI] to port number DX, advance SI
6E *OUTSB Output byte DS:[SI] to port number DX, advance SI
6F *OUTSW Output word DS:[SI] to port number DX, advance SI
1F POP DS Set DS to top of stack, increment SP by 2
07 POP ES Set ES to top of stack, increment SP by 2
8F /0 POP mw Set memory word to top of stack, increment SP by 2
58+rw POP rw Set word register to top of stack, increment SP by 2
17 POP SS Set SS to top of stack, increment SP by 2
61 *POPA Pop DI,SI,BP,SP,BX,DX,CX,AX (SP value is ignored)
9D POPF Set flags register to top of stack, increment SP by 2
0E PUSH CS Set [SP-2] to CS, then decrement SP by 2
1E PUSH DS Set [SP-2] to DS, then decrement SP by 2
06 PUSH ES Set [SP-2] to ES, then decrement SP by 2
6A ib *PUSH ib Push sign-extended immediate byte
68 iw *PUSH iw Set [SP-2] to immediate word, then decrement SP by 2
FF /6 PUSH mw Set [SP-2] to memory word, then decrement SP by 2
50+rw PUSH rw Set [SP-2] to word register, then decrement SP by 2
16 PUSH SS Set [SP-2] to SS, then decrement SP by 2
60 *PUSHA Push AX,CX,DX,BX,original SP,BP,SI,DI
9C PUSHF Set [SP-2] to flags register, then decrement SP by 2
D0 /2 RCL eb,1 Rotate 9-bit quantity (CF, EA byte) left once
D2 /2 RCL eb,CL Rotate 9-bit quantity (CF, EA byte) left CL times
C0 /2 ib *RCL eb,ib Rotate 9-bit quantity (CF, EA byte) left ib times
D1 /2 RCL ew,1 Rotate 17-bit quantity (CF, EA word) left once
D3 /2 RCL ew,CL Rotate 17-bit quantity (CF, EA word) left CL times
C1 /2 ib *RCL ew,ib Rotate 17-bit quantity (CF, EA word) left ib times
D0 /3 RCR eb,1 Rotate 9-bit quantity (CF, EA byte) right once
D2 /3 RCR eb,CL Rotate 9-bit quantity (CF, EA byte) right CL times
C0 /3 ib *RCR eb,ib Rotate 9-bit quantity (CF, EA byte) right ib times
D1 /3 RCR ew,1 Rotate 17-bit quantity (CF, EA word) right once
D3 /3 RCR ew,CL Rotate 17-bit quantity (CF, EA word) right CL times
C1 /3 ib *RCR ew,ib Rotate 17-bit quantity (CF, EA word) right ib times
F3 REP (prefix) Repeat following MOVS,LODS,STOS,INS, or OUTS CX times
65 #REPC (prefix) Repeat following CMPS or SCAS CX times or until CF=0
F3 REPE (prefix) Repeat following CMPS or SCAS CX times or until ZF=0
64 #REPNC (prefix)Repeat following CMPS or SCAS CX times or until CF=1
F2 REPNE (prefix)Repeat following CMPS or SCAS CX times or until ZF=1
F2 REPNZ (prefix)Repeat following CMPS or SCAS CX times or until ZF=0
F3 REPZ (prefix) Repeat following CMPS or SCAS CX times or until ZF=1
CB RETF Return to far caller (pop offset, then seg)
C3 RET Return to near caller (pop offset only)
CA iw RETF iw RET (far), pop offset, seg, iw bytes
C2 iw RET iw RET (near), pop offset, iw bytes pushed before Call
6-12
D0 /0 ROL eb,1 Rotate 8-bit EA byte left once
D2 /0 ROL eb,CL Rotate 8-bit EA byte left CL times
C0 /0 ib *ROL eb,ib Rotate 8-bit EA byte left ib times
D1 /0 ROL ew,1 Rotate 16-bit EA word left once
D3 /0 ROL ew,CL Rotate 16-bit EA word left CL times
C1 /0 ib *ROL ew,ib Rotate 16-bit EA word left ib times
0F 28/0 #ROL4 eb Rotate nibbles: Heb=Leb HAL,Leb=LAL LAL=Heb
D0 /1 ROR eb,1 Rotate 8-bit EA byte right once
D2 /1 ROR eb,CL Rotate 8-bit EA byte right CL times
C0 /1 ib *ROR eb,ib Rotate 8-bit EA byte right ib times
D1 /1 ROR ew,1 Rotate 16-bit EA word right once
D3 /1 ROR ew,CL Rotate 16-bit EA word right CL times
C1 /1 ib *ROR ew,ib Rotate 16-bit EA word right ib times
0F 2A/0 #ROR4 eb Rotate nibbles: Leb=Heb Heb=LAL AL=eb
9E SAHF Store AH into flags SF ZF xx AF xx PF xx CF
D0 /4 SAL eb,1 Multiply EA byte by 2, once
D2 /4 SAL eb,CL Multiply EA byte by 2, CL times
C0 /4 ib *SAL eb,ib Multiply EA byte by 2, ib times
D1 /4 SAL ew,1 Multiply EA word by 2, once
D3 /4 SAL ew,CL Multiply EA word by 2, CL times
C1 /4 ib *SAL ew,ib Multiply EA word by 2, ib times
D0 /7 SAR eb,1 Signed divide EA byte by 2, once
D2 /7 SAR eb,CL Signed divide EA byte by 2, CL times
C0 /7 ib *SAR eb,ib Signed divide EA byte by 2, ib times
D1 /7 SAR ew,1 Signed divide EA word by 2, once
D3 /7 SAR ew,CL Signed divide EA word by 2, CL times
C1 /7 ib *SAR ew,ib Signed divide EA word by 2, ib times
1C ib SBB AL,ib Subtract with borrow immediate byte from AL
1D iw SBB AX,iw Subtract with borrow immediate word from AX
80 /3 ib SBB eb,ib Subtract with borrow immediate byte from EA byte
18 /r SBB eb,rb Subtract with borrow byte register from EA byte
83 /3 ib SBB ew,ib Subtract with borrow immediate byte from EA word
81 /3 iw SBB ew,iw Subtract with borrow immediate word from EA word
19 /r SBB ew,rw Subtract with borrow word register from EA word
1A /r SBB rb,eb Subtract with borrow EA byte from byte register
1B /r SBB rw,ew Subtract with borrow EA word from word register
AE SCAS mb Compare bytes AL - ES:[DI], advance DI
AF SCAS mw Compare words AL - ES:[DI], advance DI
AE SCASB Compare bytes AX - ES:[DI], advance DI
AF SCASW Compare words AX - ES:[DI], advance DI
0F 14/0 #SETBIT eb,CL Set bit CL of eb
0F 15/0 #SETBIT ew,CL Set bit CL of ew
0F 1C/0 ib #SETBIT eb,ib Set bit ib of eb
0F 1D/0 ib #SETBIT ew,ib Set bit ib of ew
0F 01 /0 *SGDT m Store 6-byte Global Descriptor Table register to M
D0 /4 SHL eb,1 Multiply EA byte by 2, once
D2 /4 SHL eb,CL Multiply EA byte by 2, CL times
C0 /4 ib *SHL eb,ib Multiply EA byte by 2, ib times
D1 /4 SHL ew,1 Multiply EA word by 2, once
D3 /4 SHL ew,CL Multiply EA word by 2, CL times
C1 /4 ib *SHL ew,ib Multiply EA word by 2, ib times
6-13
D0 /5 SHR eb,1 Unsigned divide EA byte by 2, once
D2 /5 SHR eb,CL Unsigned divide EA byte by 2, CL times
C0 /5 ib *SHR eb,ib Unsigned divide EA byte by 2, ib times
D1 /5 SHR ew,1 Unsigned divide EA word by 2, once
D3 /5 SHR ew,CL Unsigned divide EA word by 2, CL times
C1 /5 ib *SHR ew,ib Unsigned divide EA word by 2, ib times
0F 01 /1 *SIDT m Store 6-byte Interrupt Descriptor Table register to M
0F 00 /0 *SLDT ew Store Local Descriptor Table register to EA word
0F 01 /4 *SMSW ew Store Machine Status Word to EA word
F9 STC Set carry flag
FD STD Set direction flag so SI and DI will decrement
FB STI Set interrupt enable flag, interrupts enabled
0F 31/r #STOBITS rb,rb Store AX to ES:DI,bit rb (incr. DI,rb), rb+1 bits
0F 39/0 ib #STOBITS rb,ib Store AX to ES:DI,bit rb (incr. DI,rb), ib+1 bits
AA STOS mb Store AL to byte [DI], advance DI
AB STOS mw Store AX to word [DI], advance DI
AA STOSB Store AL to byte ES:[DI], advance DI
AB STOSW Store AX to word ES:[DI], advance DI
0F 00 /1 *STR ew Store Task Register to EA word
2C ib SUB AL,ib Subtract immediate byte from AL
2D iw SUB AX,iw Subtract immediate word from AX
80 /5 ib SUB eb,ib Subtract immediate byte from EA byte
28 /r SUB eb,rb Subtract byte register from EA byte
83 /5 ib SUB ew,ib Subtract immediate byte from EA word
81 /5 iw SUB ew,iw Subtract immediate word from EA word
29 /r SUB ew,rw Subtract word register from EA word
2A /r SUB rb,eb Subtract EA byte from byte register
2B /r SUB rw,ew Subtract EA word from word register
0F 22 #SUB4S Sub CL nibbles BCD at DS:SI from ES:DI (CL even,NZ)
A8 ib TEST AL,ib AND immediate byte into AL for flags only
A9 iw TEST AX,iw AND immediate word into AX for flags only
F6 /0 ib TEST eb,ib AND immediate byte into EA byte for flags only
84 /r TEST eb,rb AND byte register into EA byte for flags only
F7 /0 iw TEST ew,iw AND immediate word into EA word for flags only
85 /r TEST ew,rw AND word register into EA word for flags only
84 /r TEST rb,eb AND EA byte into byte register for flags only
85 /r TEST rw,ew AND EA word into word register for flags only
0F 10/0 #TESTBIT eb,CL Test bit CL of eb, set Z flag
0F 11/0 #TESTBIT ew,CL Test bit CL of ew, set Z flag
0F 18/0 ib #TESTBIT eb,ib Test bit ib of eb, set Z flag
0F 19/0 ib #TESTBIT ew,ib Test bit ib of ew, set Z flag
9B WAIT Wait until BUSY pin is inactive (HIGH)
0F 00 /4 *VERR ew Set ZF=1 if segment can be read, selector ew
0F 00 /5 *VERW ew Set ZF=1 if segment can be written to, selector ew
6-14
9r XCHG AX,rw Exchange word register with AX
86 /r XCHG eb,rb Exchange byte register with EA byte
87 /r XCHG ew,rw Exchange word register with EA word
86 /r XCHG rb,eb Exchange EA byte with byte register
9r XCHG rw,AX Exchange with word register
87 /r XCHG rw,ew Exchange EA word with word register
D7 XLAT mb Set AL to memory byte [BX + unsigned AL]
D7 XLATB Set AL to memory byte DS:[BX + unsigned AL]
34 ib XOR AL,ib Exclusive-OR immediate byte into AL
35 iw XOR AX,iw Exclusive-OR immediate word into AX
80 /6 ib XOR eb,ib Exclusive-OR immediate byte into EA byte
30 /r XOR eb,rb Exclusive-OR byte register into EA byte
81 /6 iw XOR ew,iw Exclusive-OR immediate word into EA word
31 /r XOR ew,rw Exclusive-OR word register into EA word
32 /r XOR rb,eb Exclusive-OR EA byte into byte register
33 /r XOR rw,ew Exclusive-OR EA word into word register
* Starred forms will not execute on 8086/8088! See note at top of chart.
# These instructions work only on NEC chips! See note at top of chart.